home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 1122 / 1122.xpi / chrome / tabmixplus.jar / content / tabmixplus / tab / tabmix_3.xml < prev    next >
Extensible Markup Language  |  2009-10-12  |  41KB  |  1,093 lines

  1. <?xml version="1.0"?>
  2.  
  3. <!DOCTYPE bindings [
  4. <!ENTITY % identityDTD SYSTEM "chrome://tabmixplus/locale/pref-tabmix.dtd" >
  5. %identityDTD;
  6. <!ENTITY % tabmixDTD SYSTEM "chrome://tabmixplus/locale/tabmix.dtd" >
  7. %tabmixDTD;
  8. <!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
  9. %globalDTD;
  10. <!ENTITY % tabBrowserDTD SYSTEM "chrome://browser/locale/tabbrowser.dtd" >
  11. %tabBrowserDTD;
  12. ]>
  13.  
  14. <bindings id="tabxbindings_3"
  15.           xmlns="http://www.mozilla.org/xbl"
  16.           xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
  17.           xmlns:xbl="http://www.mozilla.org/xbl">
  18.  
  19.   <binding id="tabbrowser-close-tab-button"
  20.            extends="chrome://browser/content/tabbrowser.xml#tabbrowser-close-tab-button">
  21.     <handlers>
  22.       <handler event="click" button="1" action="TMP_ClosedTabs.undoCloseTab();"/>
  23.     </handlers>
  24.   </binding>
  25.  
  26.   <binding id="browser-tab" display="xul:hbox"
  27.         extends="chrome://global/content/bindings/tabbox.xml#tab">
  28.     <content chromedir="&locale.dir;"
  29.              closetabtext="&closeTab.label;">
  30.       <xul:hbox class="tab-image-left tab-startcap tab-left tab-left-border" xbl:inherits="selected,hover"/>
  31.       <xul:hbox class="tab-drag-indicator-left"/>
  32.       <xul:toolbarbutton anonid="tmp-close-button" tabindex="-1" class="tab-close-button always-left"/>
  33.       <xul:hbox flex="1" class="tab-middle box-inherit tab-image-middle tab-body" align="center" xbl:inherits="selected">
  34.         <xul:stack class="tab-icon">
  35.           <xul:image class="tab-icon-image" xbl:inherits="validate,src=image"/>
  36.           <xul:image class="tab-protect-icon" />
  37.           <xul:image class="tab-lock-icon"/>
  38.         </xul:stack>
  39.         <xul:stack class="tab-text-stack" flex="1">
  40.           <xul:progressmeter class="tab-progress" flex="2" mode="normal" value="0" xbl:inherits="value=tab-progress"/>
  41.           <xul:label class="tab-text" xbl:inherits="value=label,accesskey,crop,disabled" flex="1"/>
  42.           <xul:hbox class="showhover-box">
  43.             <xul:toolbarbutton anonid="tmp-close-button" tabindex="-1" class="showhover tabs-closebutton"/>
  44.           </xul:hbox>
  45.         </xul:stack>
  46.       </xul:hbox>
  47.       <xul:toolbarbutton anonid="tmp-close-button" tabindex="-1" class="tab-close-button always-right"/>
  48.       <xul:hbox class="tab-drag-indicator-right"/>
  49.       <xul:hbox class="tab-image-right tab-endcap tab-right tab-right-border" xbl:inherits="selected,hover"/>
  50.     </content>
  51.  
  52.     <implementation>
  53.     <field name="mOverCloseButton">
  54.      false
  55.     </field>
  56.     <field name="mIsHover">
  57.       false
  58.     </field>
  59.     <field name="mButtonId">
  60.       0
  61.     </field>
  62.     <field name="mFocusId">
  63.       0
  64.     </field>
  65.     <field name="mSelect">
  66.       0
  67.     </field>
  68.  
  69.     <property name="mouseHoverSelect" readonly="true">
  70.       <getter><![CDATA[
  71.         try {
  72.           return gTabmixPrefs.getBoolPref("extensions.tabmix.mouseOverSelect");
  73.         }
  74.         catch(e) {
  75.           return false;
  76.         }
  77.       ]]></getter>
  78.     </property>
  79.     <property name="mouseDownSelect" readonly="true">
  80.       <getter><![CDATA[
  81.         try {
  82.           return gTabmixPrefs.getBoolPref("extensions.tabmix.mouseDownSelect");
  83.         }
  84.         catch(e) {
  85.           return false;
  86.         }
  87.       ]]></getter>
  88.     </property>
  89.     <property name="mouseHoverSelectDelay" readonly="true">
  90.       <getter><![CDATA[
  91.         try {
  92.           return gTabmixPrefs.getIntPref("extensions.tabmix.mouseOverSelectDelay");
  93.         }
  94.         catch(e) {
  95.           return 250;
  96.         }
  97.       ]]></getter>
  98.     </property>
  99.     <property name="tabXDelay" readonly="true">
  100.       <getter><![CDATA[
  101.         try {
  102.           return gTabmixPrefs.getIntPref("extensions.tabmix.tabXDelay");
  103.         }
  104.         catch(e) {
  105.         return 0;
  106.         }
  107.       ]]></getter>
  108.     </property>
  109.  
  110.     <property name="baseY"
  111.               readonly="true"
  112.               onget="return this.boxObject.y+this.boxObject.height;"/>
  113.  
  114.     <method name="onMouseOver">
  115.       <parameter name="aEvent"/>
  116.       <body><![CDATA[
  117.         var anonid = aEvent.originalTarget.getAttribute("anonid");
  118.         if (anonid == "tmp-close-button")
  119.           this.mOverCloseButton = true;
  120.         this.mIsHover = true;
  121.         this.mButtonId = window.setTimeout(this.setShowButton, this.tabXDelay, this);
  122.         if (this.mouseHoverSelect)
  123.           this.mFocusId = window.setTimeout(this.doMouseHoverSelect, this.mouseHoverSelectDelay, this);
  124.       ]]></body>
  125.     </method>
  126.  
  127.     <method name="doMouseHoverSelect">
  128.       <parameter name="aTab"/>
  129.       <body><![CDATA[
  130.         if (!aTab || !aTab.parentNode)
  131.           return; // this tab already removed....
  132.  
  133.         var b = aTab.parentNode.parentNode.parentNode.parentNode;
  134.         if (b.hasAttribute("preventMouseHoverSelect"))
  135.             b.removeAttribute("preventMouseHoverSelect");
  136.         else if (aTab.mIsHover)
  137.            aTab.parentNode.selectedItem = aTab;
  138.       ]]></body>
  139.     </method>
  140.  
  141.     <method name="setShowButton">
  142.       <parameter name="aTab"/>
  143.       <body><![CDATA[
  144.         if (!aTab || !aTab.parentNode)
  145.           return; // this tab already removed....
  146.  
  147.         if ( aTab.mIsHover && aTab.getAttribute("showbutton") != "on")
  148.           aTab.setAttribute("showbutton", "on");
  149.       ]]></body>
  150.     </method>
  151.  
  152.     <method name="onMouseOut">
  153.       <parameter name="aEvent"/>
  154.       <body><![CDATA[
  155.         var anonid = aEvent.originalTarget.getAttribute("anonid");
  156.         if (anonid == "tmp-close-button")
  157.           this.mOverCloseButton = false;
  158.         this.mIsHover = false;
  159.         clearTimeout(this.mButtonId);
  160.         this.mButtonId = window.setTimeout(this.removeShowButton, this.tabXDelay, this);
  161.         if (this.mouseHoverSelect && this.mFocusId)
  162.           clearTimeout(this.mFocusId);
  163.       ]]></body>
  164.     </method>
  165.  
  166.     <method name="removeShowButton">
  167.       <parameter name="aTab"/>
  168.       <body><![CDATA[
  169.         if (!aTab || !aTab.parentNode)
  170.           return; // this tab already removed....
  171.  
  172.         if (!aTab.mIsHover && aTab.getAttribute("showbutton") != "off")
  173.           aTab.setAttribute("showbutton", "off");
  174.       ]]></body>
  175.     </method>
  176.  
  177.     <method name="onMouseCommand">
  178.       <parameter name="aEvent"/>
  179.       <body><![CDATA[
  180.         if (gIsFirefox35) {
  181.           this.style.MozUserFocus = 'ignore';
  182.           this.clientTop; // just using this to flush style updates
  183.         }
  184.         if ( this == this.parentNode.selectedItem ) {
  185.           this.setAttribute("clickOnCurrent","true");
  186.         }
  187.         // don't allow mouse click with modifiers to select tab
  188.         else if (!aEvent.shiftKey && !aEvent.ctrlKey && !aEvent.altKey && !aEvent.metaKey) {
  189.           function TMclickSetTab(tab) {
  190.             if (tab.parentNode)
  191.               tab.parentNode._selectNewTab(tab);
  192.           }
  193.           this.mSelect = setTimeout(TMclickSetTab, 0, this);
  194.         }
  195.       ]]></body>
  196.     </method>
  197.  
  198.     <method name="clearTimeouts">
  199.       <body><![CDATA[
  200.         let timeouts = ["mSelect", "mFocusId", "mButtonId", "autoReloadTimerID"];
  201.         timeouts.forEach(function(aTimeout) {
  202.           if (aTimeout in this && this[aTimeout]) {
  203.             clearTimeout(this[aTimeout]);
  204.             this[aTimeout] = null;
  205.           }
  206.         });
  207.         this.removeEventListener("mousedown", this.TMP_mousedownEventHandler, true);
  208.       ]]></body>
  209.     </method>    
  210.  
  211.       <field name="TMP_mousedownEventHandler" readonly="true">
  212.       <![CDATA[({
  213.          /*
  214.             XXX check if we still need this
  215.          */
  216.          mTab: this,
  217.          handleEvent: function handleEvent(aEvent) {
  218.            if (aEvent.button != "0" || aEvent.target.localName != "tab")
  219.              return;
  220.  
  221.            var anonid = aEvent.originalTarget.getAttribute("anonid");
  222.            if (this.mTab != this.mTab.parentNode.selectedItem &&   /* Not selected yet */
  223.                  anonid != "tmp-close-button" &&
  224.                  (aEvent.shiftKey || aEvent.ctrlKey || aEvent.altKey || aEvent.metaKey)) {
  225.              aEvent.stopPropagation();
  226.              return;
  227.            }
  228.  
  229.            if (this.mTab.mouseDownSelect && anonid != "tmp-close-button")
  230.              return;
  231.  
  232.            aEvent.stopPropagation();
  233.          }
  234.       })]]>
  235.       </field>
  236.  
  237.       <constructor>
  238.          <![CDATA[
  239.             if (this._inited)
  240.                return;
  241.  
  242.             this._inited = true;
  243.             this.addEventListener("mousedown", this.TMP_mousedownEventHandler, true);
  244.          ]]>
  245.       </constructor>
  246.  
  247.       <destructor>
  248.         <![CDATA[
  249.             this.clearTimeouts();
  250.         ]]>
  251.       </destructor>
  252.  
  253.     </implementation>
  254.  
  255.     <handlers>
  256.       <handler event="mouseover">
  257.       <![CDATA[
  258.         this.onMouseOver(event);
  259.       ]]>
  260.       </handler>
  261.       <handler event="mouseout">
  262.       <![CDATA[
  263.         this.onMouseOut(event);
  264.       ]]>
  265.       </handler>
  266.  
  267.       <handler event="click" button="0">
  268.       <![CDATA[
  269.         var anonid = event.originalTarget.getAttribute("anonid");
  270.         if (anonid != "tmp-close-button" && !this.mouseDownSelect) {
  271.           this.onMouseCommand(event);
  272.         }
  273.       ]]>
  274.       </handler>
  275.  
  276.       <handler event="dragstart" phase="capturing">
  277.         if (gIsFirefox35)
  278.           this.style.MozUserFocus = '';
  279.       </handler>
  280.       <handler event="mousedown" button="0" phase="capturing">
  281.       <![CDATA[
  282.         // prevent chrome://global/content/bindings/tabbox.xml#tab mousedown handler
  283.         if (this.mOverCloseButton)
  284.           event.stopPropagation();
  285.         else if (this.mouseDownSelect)
  286.           this.onMouseCommand(event);
  287.         else {
  288.           if (gIsFirefox35) {
  289.             this.style.MozUserFocus = 'ignore';
  290.             this.clientTop; // just using this to flush style updates
  291.           }
  292.           event.stopPropagation();
  293.         }
  294.       ]]>
  295.       </handler>
  296.       <handler event="mousedown" button="1">
  297.         if (gIsFirefox35) {
  298.           this.style.MozUserFocus = 'ignore';
  299.           this.clientTop;
  300.         }
  301.       </handler>
  302.       <handler event="mousedown" button="2">
  303.         if (gIsFirefox35) {
  304.           this.style.MozUserFocus = 'ignore';
  305.           this.clientTop;
  306.         }
  307.       </handler>
  308.       <handler event="mouseup">
  309.         if (gIsFirefox35)
  310.           this.style.MozUserFocus = '';
  311.       </handler>
  312.     </handlers>
  313.   </binding>
  314.  
  315.   <!-- tabbrowser-tabs bindings for Firefox 3.0+ -->
  316.   <!-- revised by CPU to support more themes -->
  317.   <binding id="scroll-tabs_3"
  318.             extends="chrome://browser/content/tabbrowser.xml#tabbrowser-tabs">
  319.     <resources>
  320.       <stylesheet src="chrome://global/skin/scrollbox.css"/>
  321.       <stylesheet src="chrome://tabmixplus/skin/mac.css"/>
  322.     </resources>
  323.     <content hidebutton="true">
  324.       <xul:stack flex="1" class="tabs-stack">
  325.         <xul:vbox class="tmp-tabs-bottom">
  326.           <xul:spacer flex="1"/>
  327.           <xul:hbox class="tabs-bottom" align="center"/>
  328.         </xul:vbox>
  329.         <xul:hbox class="tabs-container"
  330.                   xbl:inherits="overflow,flowing,scrollbutton-up,newtab_side">
  331.           <xul:box id="tabs-newTab" class="tabs-newTab" orient="horizontal">
  332.             <xul:vbox id="tabs-newbutton-box" class="tabs-newtab-topbox">
  333.               <xul:toolbarbutton class="tabs-newtab-button tabs-newbutton" anonid="newtab-button" id="tabs-newbutton"
  334.                                  xbl:inherits="platform"
  335.                                  command="cmd_newNavigatorTab" chromedir="&locale.dir;"
  336.                                  tooltiptext="&clicktab.addtab;"
  337.                                  ondblclick="event.stopPropagation();"/>
  338.             </xul:vbox>
  339.           </xul:box>
  340.  
  341.           <xul:spacer id="tabs-left-space"/>
  342.           <xul:hbox class="tabbrowser-arrowscrollbox tabmix_scrollbuttons_box" _side="left" type="tabmix"
  343.                     xbl:inherits="flowing,collapsed=underflow,scrollbutton-up,Mac">
  344.             <xul:toolbarbutton class="scrollbutton-up" orient="horizontal" scrollIndex="-1"
  345.                                chromedir="&locale.dir;"
  346.                                anonid="scrollbutton-up"
  347.                                xbl:inherits="disabled=disableScrollTabsLeft"/>
  348.           </xul:hbox>
  349.           <xul:scrollbox class="tabs-frame tabbrowser-arrowscrollbox" type="tabmix-scrollbox"
  350.                          anonid="scroll-tabs-frame" orient="horizontal" flex="1">
  351.             <children includes="tab"/>
  352.             <xul:toolbarbutton class="tabs-newtab-button"
  353.                                command="cmd_newNavigatorTab" chromedir="&locale.dir;"
  354.                                tooltiptext="&clicktab.addtab;"/>
  355.           </xul:scrollbox>
  356.           <xul:box class="tabbrowser-arrowscrollbox tabmix_scrollbuttons_box" _side="right" type="tabmix"
  357.                    xbl:inherits="flowing,collapsed=underflow,scrollbutton-up,Mac">
  358.             <xul:toolbarbutton class="scrollbutton-up" orient="horizontal" scrollIndex="-1"
  359.                                chromedir="&locale.dir;"
  360.                                anonid="scrollbutton-up"
  361.                                xbl:inherits="disabled=disableScrollTabsLeft"/>
  362.             <xul:toolbarbutton class="scrollbutton-down" orient="horizontal" scrollIndex="1"
  363.                                chromedir="&locale.dir;"
  364.                                anonid="scrollbutton-down"
  365.                                xbl:inherits="disabled=disableScrollTabsRight,notonbottom"/>
  366.           </xul:box>
  367.           <xul:spacer id="tabs-right-space"/>
  368.  
  369.           <xul:vbox id="alltabs-place-holder"/>
  370.           <xul:stack align="center" pack="end" chromedir="&locale.dir;" class="tabs-alltabs-stack">
  371.             <xul:hbox flex="1" class="tabs-alltabs-box tmp-alltabs-3" anonid="alltabs-box"/>
  372.             <xul:hbox flex="1" class="tabs-alltabs-box-animate tmp-alltabs-3" anonid="alltabs-box-animate"/>
  373.             <xul:toolbarbutton class="tabs-alltabs-button tmp-alltabs-3" type="menu" anonid="alltabs-button"
  374.                                tooltipstring="&listAllTabs.label;">
  375.               <xul:menupopup class="tabs-alltabs-popup"
  376.                              oncommand="event.stopPropagation();"
  377.                              onclick="event.stopPropagation();"
  378.                              anonid="alltabs-popup"
  379.                              position="after_end"/>
  380.             </xul:toolbarbutton>
  381.           </xul:stack>
  382.  
  383.           <xul:toolbarbutton anonid="tabs-closebutton"
  384.                              class="close-button tabs-closebutton" chromedir="&locale.dir;" tooltiptext="&closeTab.label;"/>
  385.  
  386.         </xul:hbox>
  387.       </xul:stack>
  388.       <xul:hbox anonid="arrowscrollbox" hidden="true" class="tabbrowser-arrowscrollbox"/>
  389.     </content>
  390.  
  391.     <implementation implements="nsITimerCallback, nsIDOMEventListener">
  392.       <constructor>
  393.         <![CDATA[
  394.           window.removeEventListener("resize", this, false);
  395.           if (this.tabmix_inited)
  396.              return;
  397.  
  398.           this.tabmix_inited = true;
  399.           this.canScrollTabsLeft = false;
  400.           this.canScrollTabsRight = false;
  401.           this.firstChild.setAttribute("flst_id", new Date().getTime());
  402.           this.firstChild.setAttribute("visited", true);
  403.           var tabBrowser = document.getElementById("content");
  404.           try {
  405.             TMP_beforStartup(tabBrowser, this);
  406.             TMP_ProgressListener.startup(tabBrowser);
  407.           } catch (ex) {TMP_ASSERT(ex);}
  408.         ]]>
  409.       </constructor>
  410.  
  411.       <field name="nextTab">1</field>
  412.  
  413.       <field name="tabstrip" readonly="true">
  414.         document.getAnonymousElementByAttribute(this, "anonid", "scroll-tabs-frame");
  415.       </field>
  416.  
  417.       <field name="tabstripInnerbox" readonly="true">
  418.         document.getAnonymousElementByAttribute(this.tabstrip, "class", "box-inherit scrollbox-innerbox");
  419.       </field>
  420.  
  421.       <field name="mTabstrip" readonly="true">
  422.         document.getAnonymousElementByAttribute(this, "anonid", "scroll-tabs-frame");
  423.       </field>
  424.  
  425.       <field name="mTabstripClosebutton" readonly="true">
  426.         document.getAnonymousElementByAttribute(this, "anonid", "tabs-closebutton");
  427.       </field>
  428.  
  429.       <field name="_downBoxAnimate">
  430.         document.getAnonymousElementByAttribute(this, "anonid", "scrollbutton-down");
  431.       </field>
  432.  
  433.       <field name="mTabsNewtabButton">
  434.         document.getAnonymousElementByAttribute(tabContainer, "class", "tabs-newtab-button");
  435.       </field>
  436.  
  437.       <method name="adjustTabstrip">
  438.         <parameter name="aRemovingTab"/>
  439.         <body><![CDATA[
  440.             // we don't use adjustTabstrip in tabmix
  441.             return;
  442.         ]]></body>
  443.       </method>
  444.  
  445.       <property name="canScrollTabsLeft">
  446.         <getter><![CDATA[
  447.           return !this.hasAttribute("disableScrollTabsLeft");
  448.         ]]></getter>
  449.         <setter><![CDATA[
  450.           if(val!=this.canScrollTabsLeft) {
  451.             if(val) this.removeAttribute("disableScrollTabsLeft");
  452.             else this.setAttribute("disableScrollTabsLeft","true");
  453.             this.overflow = (val || this.canScrollTabsRight);
  454.           }
  455.           return val;
  456.         ]]></setter>
  457.       </property>
  458.  
  459.       <property name="canScrollTabsRight">
  460.         <getter><![CDATA[
  461.           return !this.hasAttribute("disableScrollTabsRight");
  462.         ]]></getter>
  463.         <setter><![CDATA[
  464.           if(val!=this.canScrollTabsRight) {
  465.             if(val) this.removeAttribute("disableScrollTabsRight");
  466.             else this.setAttribute("disableScrollTabsRight","true");
  467.             this.overflow = (this.canScrollTabsLeft || val);
  468.           }
  469.           return val;
  470.         ]]></setter>
  471.       </property>
  472.  
  473.       <method name="adjustScrollTabsLeft">
  474.         <body><![CDATA[
  475.             var rtl = window.getComputedStyle(this.parentNode, null).direction == "rtl" && gTabmixPrefs.getIntPref("extensions.tabmix.tabBarMode") != 2;
  476.             if (rtl)
  477.               this.canScrollTabsRight = this._collapsedTabs > 0;
  478.             else
  479.               this.canScrollTabsLeft = this._collapsedTabs > 0;
  480.         ]]></body>
  481.       </method>
  482.  
  483.       <method name="adjustScrollTabsRight">
  484.         <body><![CDATA[
  485.             var rtl = window.getComputedStyle(this.parentNode, null).direction == "rtl" && gTabmixPrefs.getIntPref("extensions.tabmix.tabBarMode") != 2;
  486.             if (rtl)
  487.               this.canScrollTabsLeft = (this.boxObject.width == 0 || this.childNodes.length <= this.maxRow) ? false : !this.lastTabVisible;
  488.             else
  489.               this.canScrollTabsRight = (this.boxObject.width == 0 || this.childNodes.length <= this.maxRow) ? false : !this.lastTabVisible;
  490.         ]]></body>
  491.       </method>
  492.  
  493.       <property name="overflow">
  494.         <getter><![CDATA[
  495.           return this.getAttribute("overflow");
  496.         ]]></getter>
  497.         <setter><![CDATA[
  498.           if (val != this.overflow) {
  499.             var tabBrowser = gisToolbarMode ? document.getElementById("content") : null ;
  500.             if (val) {
  501.               if (this.getAttribute("flowing") == "singlebar")
  502.                 return !val;
  503.               if (tabBrowser && tabBrowser._toolbarItem)
  504.                 tabBrowser._toolbarItem.setAttribute("overflow", "true");
  505.               this.setAttribute("overflow", "true");
  506.               this.removeAttribute("underflow");
  507.             }
  508.             else {
  509.               if (tabBrowser && tabBrowser._toolbarItem)
  510.                 tabBrowser._toolbarItem.removeAttribute("overflow");
  511.               this.removeAttribute("overflow");
  512.               this.setAttribute("underflow", "true");
  513.             }
  514.           }
  515.           return val;
  516.         ]]></setter>
  517.       </property>
  518.  
  519.       <property name="lastTabVisible" readonly="true">
  520.         <getter>
  521.         <![CDATA[
  522.               var index;
  523.               if (window.getComputedStyle(this.parentNode, null).direction == "rtl" &&
  524.                              !this.hasAttribute("multibar"))
  525.                 index = 0;
  526.               else
  527.                 index = this.childNodes.length - 1;
  528.             return this.isTabVisible(index);
  529.         ]]>
  530.         </getter>
  531.       </property>
  532.  
  533.       <!--
  534.         check that we have enough room to show new tab button after the last tab in the current row
  535.         we don't want the button to be on the next row when the tab is on the current row
  536.       -->
  537.       <field name="_newTabButtonWidth">21</field>
  538.       <field name="_rightNewTabButton">null</field>
  539.       <field name="_checkNewtabButtonvisibility">false</field>
  540.       <method name="adjustNewtabButtonvisibility">
  541.         <body><![CDATA[
  542.           if (!this._checkNewtabButtonVisibility || this.tabstrip.orient == "vertical")
  543.             return;
  544.           var tsbo = this.tabstrip.boxObject;
  545.           var tsboEnd = tsbo.screenX + tsbo.width + (this._rightNewTabButton ? this._rightNewTabButton.boxObject.width: 0);
  546.           var previousTab = this.lastChild.previousSibling;
  547.           var previousTabEnd = previousTab ? previousTab.boxObject.screenX + previousTab.boxObject.width: 0;
  548.           var lastTabEnd = previousTabEnd + this.lastChild.boxObject.width;
  549.           if (lastTabEnd <= tsboEnd) {
  550.             var buttonEnd = lastTabEnd + this._newTabButtonWidth;
  551.             if (buttonEnd > tsboEnd) {
  552.               if (!this.hasAttribute("disAllowNewtabbutton"))
  553.                 this.setAttribute("disAllowNewtabbutton", true);
  554.               return;
  555.             }
  556.           }
  557.           if (this.hasAttribute("disAllowNewtabbutton"))
  558.             this.removeAttribute("disAllowNewtabbutton");
  559.         ]]></body>
  560.       </method>
  561.  
  562.       <field name="_collapsedTabs">0</field>
  563.       <property name="collapsedTabs"
  564.           onget="return this._collapsedTabs">
  565.         <setter>
  566.         <![CDATA[
  567.           const tabs = this.childNodes;
  568.           var i;
  569.  
  570.           var rtl = window.getComputedStyle(this.parentNode, null).direction == "rtl" && gTabmixPrefs.getIntPref("extensions.tabmix.tabBarMode") != 2;
  571.           if (val > this._collapsedTabs && this.lastTabVisible ) {
  572.             if (rtl)
  573.               this.canScrollTabsLeft = false;
  574.             else
  575.               this.canScrollTabsRight = false;
  576.             val = this._collapsedTabs;
  577.             return val;
  578.           }
  579.           if ( val < 0 ) val = 0;
  580.           if (rtl) {
  581.             for(i = 0; i < tabs.length - val; i++) {
  582.               if (tabs[i].collapsed)
  583.                 tabs[i].collapsed = false;
  584.             }
  585.             for(i = tabs.length - val; i < tabs.length; i++) {
  586.               if (!tabs[i].collapsed)
  587.                 tabs[i].collapsed = true;
  588.             }
  589.           }
  590.           else {
  591.             for(i = 0; i < val; i++) {
  592.               if (!tabs[i].collapsed)
  593.                 tabs[i].collapsed = true;
  594.             }
  595.             for(i = val; i < tabs.length; i++) {
  596.               if (tabs[i].collapsed)
  597.                 tabs[i].collapsed = false;
  598.             }
  599.           }
  600.  
  601.           this._collapsedTabs = val;
  602.  
  603.           var _left = (val != 0);
  604.           var _right = this.boxObject.width == 0 ? false : !this.lastTabVisible;
  605.           this.canScrollTabsLeft = rtl ? _right : _left;
  606.           this.canScrollTabsRight = rtl ? _left : _right;
  607.  
  608.           return val;
  609.         ]]>
  610.         </setter>
  611.       </property>
  612.  
  613.       <field name="_scrollBoxObject">null</field>
  614.       <property name="scrollBoxObject" readonly="true">
  615.         <getter><![CDATA[
  616.           if (!this._scrollBoxObject) {
  617.             this._scrollBoxObject =
  618.               this.tabstrip.boxObject
  619.                              .QueryInterface(Components.interfaces.nsIScrollBoxObject);
  620.           }
  621.           return this._scrollBoxObject;
  622.         ]]></getter>
  623.       </property>
  624.  
  625.       <method name="isTabVisible">
  626.         <parameter name="aIndex"/>
  627.         <body>
  628.         <![CDATA[
  629.           const tabs = this.childNodes;
  630.           if (tabs.length == 1)
  631.             return true;
  632.  
  633.           if (aIndex < 0 || aIndex > tabs.length - 1)
  634.             return false;
  635.  
  636.           var rtl = window.getComputedStyle(this.parentNode, null).direction == "rtl" && gTabmixPrefs.getIntPref("extensions.tabmix.tabBarMode") != 2;
  637.           if (!rtl && this.collapsedTabs > aIndex)
  638.             return false;
  639.  
  640.           if (rtl && aIndex > tabs.length - 1 - this.collapsedTabs)
  641.             return false;
  642.  
  643.           var tabstripWidth = this.tabstrip.boxObject.width;
  644.           var tabstripEnd = this.tabstrip.boxObject.screenX + tabstripWidth;
  645.           // Session Manager extesion add tabs too soon for us to check visibility properly
  646.           // we remove SM_restart after timeout see tabmix.js onWindowOpen
  647.           if (this.hasAttribute("SM_restart") && tabstripWidth < 250)
  648.             return true;
  649.  
  650.           var tab = tabs[aIndex];
  651.           //XXX this hack is for the case that the width of the tabbar is round nuber of tabs
  652.           // when we reach to that number of tabs and tabs need to start shrinking.          
  653.           if (this.tabstripInnerbox && !this.overflow) {
  654.             if (this.tabstripInnerbox.boxObject.screenX + this.tabstripInnerbox.boxObject.width > tabstripEnd)
  655.               return false;
  656.             else if ( this.getAttribute("multibar") == "scrollbar" ) {
  657.               if ( tab.baseY > this.parentNode.boxObject.y + this.parentNode.boxObject.height + 2)
  658.                 return false;
  659.             }
  660.             return true;
  661.           }
  662.  
  663.           if (tab.boxObject.screenX + tab.boxObject.width > tabstripEnd)
  664.             return false;
  665.           else if ( this.getAttribute("multibar") == "scrollbar" ) {
  666.             if ( tab.baseY > this.parentNode.boxObject.y + this.parentNode.boxObject.height + 2)
  667.               return false;
  668.           }
  669.           return true;
  670.         ]]>
  671.         </body>
  672.       </method>
  673.  
  674.       <method name="ensureTabIsVisible">
  675.         <parameter name="aIndex"/>
  676.         <body>
  677.         <![CDATA[
  678.           if ((!this.canScrollTabsLeft && !this.canScrollTabsRight) || this.boxObject.width == 0 || this.isTabVisible(aIndex))
  679.              return;
  680.  
  681.           const tabs = this.childNodes;
  682.           if (aIndex < 0 || aIndex > tabs.length - 1)
  683.             return;
  684.           var tab = tabs[aIndex];
  685.  
  686.           var amount, i, j;
  687.           if ( this.tabstrip.boxObject.width < 250 )
  688.             return;
  689.  
  690.           if ( gTabmixPrefs.getIntPref("extensions.tabmix.tabBarMode") != 2 ) {
  691.             if (window.getComputedStyle(this.parentNode, null).direction == "ltr") {
  692.               if (aIndex < this.collapsedTabs)
  693.                 this.collapsedTabs = aIndex;
  694.               else {
  695.                 var amountToCollapse = tab.boxObject.screenX + tab.boxObject.width - this.tabstrip.boxObject.screenX - this.tabstrip.boxObject.width;
  696.                 if(amountToCollapse > 0) {
  697.                   amount = 0;
  698.                   i = this.collapsedTabs;
  699.                   while(amount < amountToCollapse) {
  700.                     amount += tabs[i].boxObject.width;
  701.                     i++;
  702.                   }
  703.                   this.collapsedTabs = i;
  704.                 }
  705.               }
  706.             }
  707.             else { // RTL
  708.               if (aIndex > tabs.length - 1 - this.collapsedTabs)
  709.                 this.collapsedTabs = tabs.length - 1 - aIndex;
  710.               else {
  711.                 var amountToCollapse = tab.boxObject.screenX + tab.boxObject.width - this.tabstrip.boxObject.screenX - this.tabstrip.boxObject.width;
  712.                 if(amountToCollapse > 0) {
  713.                   amount = 0;
  714.                   i = this.collapsedTabs;
  715.                   while(amount < amountToCollapse) {
  716.                     amount += tabs[tabs.length - 1 - i].boxObject.width;
  717.                     i++;
  718.                   }
  719.                   this.collapsedTabs = i;
  720.                 }
  721.               }
  722.             }
  723.           }
  724.           else if ( this.getAttribute("multibar") == "scrollbar" ) {
  725.             if (aIndex < this.collapsedTabs) {
  726.                while (aIndex < this.collapsedTabs)
  727.                   this.rowScroll(-1);
  728.             }
  729.             else {
  730.                var bottom = this.parentNode.boxObject.y + this.parentNode.boxObject.height + 2;
  731.                while (tab.baseY > bottom )
  732.                   this.rowScroll(+1);
  733.             }
  734.           }
  735.         ]]>
  736.         </body>
  737.       </method>
  738.  
  739.       <method name="tabsScroll">
  740.         <parameter name="factor"/>
  741.         <body>
  742.         <![CDATA[
  743.           if ( this.getAttribute("flowing") == "multibar" &&
  744.             this.getAttribute("multibar") == "scrollbar" )
  745.               this.rowScroll(factor);
  746.           else {
  747.             var rtl = window.getComputedStyle(this.parentNode, null).direction == "rtl" && gTabmixPrefs.getIntPref("extensions.tabmix.tabBarMode") != 2;
  748.             if (rtl) factor = factor * -1;
  749.             this.collapsedTabs += factor;
  750.           }
  751.         ]]>
  752.         </body>
  753.       </method>
  754.  
  755.       <method name="_animatClollapse">
  756.         <parameter name="aTab"/>
  757.         <parameter name="amount"/>
  758.         <body>
  759.         <![CDATA[
  760.           if (!aTab || !aTab.parentNode)
  761.             return;
  762.  
  763.           aTab.setAttribute("width", aTab.boxObject.width * amount);
  764.         ]]>
  765.         </body>
  766.       </method>
  767.  
  768.       <method name="_endClollapse">
  769.         <parameter name="aTab"/>
  770.         <parameter name="factor"/>
  771.         <body>
  772.         <![CDATA[
  773.           if (!aTab || !aTab.parentNode)
  774.             return;
  775.  
  776.           aTab.parentNode.collapsedTabs += factor;
  777.           aTab.width = 0;
  778.           aTab.setAttribute("flex", "100");
  779.         ]]>
  780.         </body>
  781.       </method>
  782.  
  783.       <method name="rowScroll">
  784.         <parameter name="factor"/>
  785.         <body>
  786.         <![CDATA[
  787.           const tabs = this.childNodes;
  788.           var i, firstVisibleIndex = this.collapsedTabs;
  789.           var currentFirstTab = tabs[firstVisibleIndex];
  790.           var top = this.topTabY;
  791.           if (factor == -1 ) {
  792.             // push first visible tab to 2nd row or reveal all hidden tabs
  793.             for (i = firstVisibleIndex - 1; i >= 0; i--) {
  794.               tabs[i].collapsed = false;
  795.               if (this.getTabRowNumber(currentFirstTab, top) == 2)
  796.                 break;
  797.             }
  798.           }
  799.           else {
  800.             // find index of the first tab in 2nd row, so we can hide all tab before it
  801.             for (i = firstVisibleIndex + 1; i < tabs.length; i++) {
  802.               if (this.getTabRowNumber(tabs[i], top) == 2)
  803.                 break;
  804.             }
  805.           }
  806.           if (i != firstVisibleIndex)
  807.             this.collapsedTabs = i;
  808.         ]]>
  809.         </body>
  810.       </method>
  811.  
  812.       <field name="_maxRow">0</field>
  813.       <property name="maxRow">
  814.         <getter><![CDATA[
  815.           var row = gTabmixPrefs.getIntPref("extensions.tabmix.tabBarMaxRow");
  816.           if ( row < 2 ) {
  817.             row = 2;
  818.             gTabmixPrefs.setIntPref("extensions.tabmix.tabBarMaxRow", 2);
  819.           }
  820.           if (this._maxRow != row) {
  821.             if (row > 2) {
  822.               if (!this.hasAttribute("notonbottom"))
  823.                 this.setAttribute("notonbottom", "true");
  824.             }
  825.             else
  826.               this.removeAttribute("notonbottom");
  827.  
  828.             this._maxRow = row;
  829.           }
  830.  
  831.           return row;
  832.         ]]></getter>
  833.       </property>
  834.  
  835.       <property name="topTabY" readonly="true">
  836.         <getter><![CDATA[
  837.           var topTab = this.childNodes[this.collapsedTabs];
  838.           return topTab.boxObject.y - parseInt(window.getComputedStyle(topTab, null).marginTop.replace("px",""));
  839.         ]]></getter>
  840.       </property>
  841.  
  842.       <property name="lastTabRowNumber"
  843.                 readonly="true"
  844.                 onget="return this.getTabRowNumber(this.lastChild, this.topTabY);"/>
  845.  
  846.       <method name="getTabRowNumber">
  847.         <parameter name="aTab"/>
  848.         <parameter name="aTop"/>
  849.         <body><![CDATA[
  850.           var height = aTab.boxObject.height;
  851.           if (height == 0) // don't panic
  852.             return;
  853.  
  854.           var marginTop = parseInt(window.getComputedStyle(aTab, null).marginTop.replace("px",""));
  855.           var marginBottom = parseInt(window.getComputedStyle(aTab, null).marginBottom.replace("px",""));
  856.           height += marginTop + marginBottom;
  857.           var tabBottom = aTab.boxObject.y - marginTop + height
  858.           return Math.round((tabBottom - aTop)/height);          
  859.         ]]></body>
  860.       </method>
  861.  
  862.       <method name="_handleTabSelect">
  863.         <body><![CDATA[
  864.           this.ensureTabIsVisible(this.selectedIndex);
  865.         ]]></body>
  866.       </method>
  867.  
  868.       <method name="_notifyBackgroundTab">
  869.         <parameter name="aTab"/>
  870.         <body><![CDATA[
  871.           // Is the new tab already completely visible?
  872.           if (this.isTabVisible(aTab._tPos))
  873.             return;
  874.  
  875.           var tsbo = this.tabstrip.boxObject;
  876.           var ctbo = aTab.boxObject;
  877.           var selbo = this.selectedItem.boxObject;
  878.           if ( gTabmixPrefs.getIntPref("extensions.tabmix.tabBarMode") != 2 ) {
  879.             var ctboStart = ctbo.screenX;
  880.             var ctboEnd = ctboStart + ctbo.width;
  881.  
  882.             var selStart = selbo.screenX;
  883.             var selEnd = selStart + selbo.width;
  884.  
  885.             // Can we make both the new tab and the selected tab completely visible?
  886.             if (Math.max(ctboEnd - selStart, selEnd - ctboStart) <= tsbo.width) {
  887.               this.ensureTabIsVisible(aTab._tPos);
  888.               return;
  889.             }
  890.           }
  891.           else if (this.selectedIndex >= this.collapsedTabs) {
  892.             var ctboTop = ctbo.screenY;
  893.             var ctboBottom = ctboTop + ctbo.height;
  894.  
  895.             var selTop = selbo.screenY;
  896.             var selBottom = selTop + selbo.height;
  897.             if (Math.max(selBottom - ctboTop, ctboBottom - selTop) <= tsbo.height) {
  898.               this.ensureTabIsVisible(aTab._tPos);
  899.               return;
  900.             }
  901.           }
  902.  
  903.           this.ensureTabIsVisible(this.selectedIndex);
  904.  
  905.           if (gIsFirefox35) {
  906.             this._stopAnimation();
  907.  
  908.             var self = this;
  909.             this._animateBaseColor =
  910.               window.getComputedStyle(this._downBoxAnimate, null)
  911.                     .outlineColor
  912.                     .replace(/^rgb\((.*)\)$/, "rgba($1, 1)")
  913.                     .replace(/([^, ]*)\)/, function (m0, m1) {
  914.                       self._animateBaseOpacity = parseFloat(m1);
  915.                       return "$opacity)";
  916.                     });
  917.  
  918.             // start the flash timer
  919.             this._animateStep = 0;
  920.  
  921.             var outlineWidth =
  922.               Math.ceil(Math.min(this._downBoxAnimate.clientHeight,
  923.                                  this._downBoxAnimate.clientWidth) * .6) + "px";
  924.             this._downBoxAnimate.style.outlineWidth = outlineWidth;
  925.             this._downBoxAnimate.style.outlineOffset = "-" + outlineWidth;
  926.             this._downBoxAnimate.style.outlineColor = "rgba(0,0,0,0)";
  927.             this._downBoxAnimate.style.outlineStyle = "solid";
  928.           }
  929.           else {
  930.             // start the flash timer
  931.             this._animateStep = 0;
  932.           }
  933.  
  934.           if (!this._animateTimer)
  935.             this._animateTimer =
  936.               Components.classes["@mozilla.org/timer;1"]
  937.                         .createInstance(Components.interfaces.nsITimer);
  938.           else if (!gIsFirefox35)
  939.              this._animateTimer.cancel();
  940.  
  941.           this._animateTimer.initWithCallback(this, this._animateDelay,
  942.                                               this._animateTimer.TYPE_REPEATING_SLACK);
  943.         ]]></body>
  944.       </method>
  945.  
  946.     </implementation>
  947.   </binding>
  948.  
  949.   <binding id="tabmix-scroll-button"
  950.       extends="chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton-image">
  951.  
  952.     <implementation implements="nsITimerCallback, nsIDOMEventListener">
  953.       <constructor><![CDATA[
  954.         try {
  955.           this._scrollDelay =
  956.              gTabmixPrefs.getIntPref("extensions.tabmix.clickToScroll.scrollDelay");
  957.         }
  958.         catch (ex) {      }
  959.  
  960.         this.mTabContainer = document.getBindingParent(this);
  961.         this._scrollIndex = this.getAttribute("scrollIndex") == "1" ? 1 : -1;
  962.         if (window.getComputedStyle(this.mTabContainer, null).direction == "rtl")
  963.           this._scrollIndex *= -1;
  964.         this._side = this._scrollIndex == 1 ? "right" : "left";
  965.       ]]></constructor>
  966.  
  967.       <destructor><![CDATA[
  968.         // Release timer to avoid reference cycles.
  969.         if (this._scrollTimer) {
  970.           this._scrollTimer.cancel();
  971.           this._scrollTimer = null;
  972.         }
  973.       ]]></destructor>
  974.  
  975.       <field name="_scrollIndex">0</field>
  976.       <field name="_scrollDelay">150</field>
  977.  
  978.       <method name="notify">
  979.         <parameter name="aTimer"/>
  980.         <body>
  981.         <![CDATA[
  982.           if (this.hasAttribute("disabled")) {
  983.             this._stopScroll();
  984.             return;
  985.           }
  986.  
  987.           if (!document)
  988.             aTimer.cancel();
  989.  
  990.           this.mTabContainer.tabsScroll(this._scrollIndex);
  991.         ]]>
  992.         </body>
  993.       </method>
  994.  
  995.       <method name="_startScroll">
  996.         <body><![CDATA[
  997.           if (this.hasAttribute("disabled")) {
  998.             this._stopScroll();
  999.             return;
  1000.           }
  1001.           var scrollDelay = this._scrollDelay;
  1002.           if (!this._scrollTimer)
  1003.             this._scrollTimer =
  1004.               Components.classes["@mozilla.org/timer;1"]
  1005.                         .createInstance(Components.interfaces.nsITimer);
  1006.           else
  1007.             this._scrollTimer.cancel();
  1008.  
  1009.           this._scrollTimer.initWithCallback(this, scrollDelay,
  1010.                                              this._scrollTimer.TYPE_REPEATING_SLACK);
  1011.           this.notify(this._scrollTimer);
  1012.           this._mousedown = true;
  1013.         ]]>
  1014.         </body>
  1015.       </method>
  1016.  
  1017.       <method name="_stopScroll">
  1018.         <body><![CDATA[
  1019.           if (this._scrollTimer)
  1020.             this._scrollTimer.cancel();
  1021.           this._mousedown = false;
  1022.         ]]></body>
  1023.       </method>
  1024.  
  1025.       <method name="_pauseScroll">
  1026.         <body><![CDATA[
  1027.           if (this._mousedown) {
  1028.             this._stopScroll();
  1029.             this._mousedown = true;
  1030.             document.addEventListener("mouseup", this, false);
  1031.             document.addEventListener("blur", this, true);
  1032.           }
  1033.         ]]></body>
  1034.       </method>
  1035.  
  1036.       <method name="_continueScroll">
  1037.         <body><![CDATA[
  1038.           if (this._mousedown)
  1039.             this._startScroll();
  1040.         ]]></body>
  1041.       </method>
  1042.  
  1043.       <method name="handleEvent">
  1044.         <parameter name="aEvent"/>
  1045.         <body><![CDATA[
  1046.           if (aEvent.type == "mouseup" ||
  1047.               aEvent.type == "blur" && aEvent.target == document) {
  1048.             this._mousedown = false;
  1049.             document.removeEventListener("mouseup", this, false);
  1050.             document.removeEventListener("blur", this, true);
  1051.           }
  1052.         ]]></body>
  1053.       </method>
  1054.     </implementation>
  1055.  
  1056.     <handlers>
  1057.       <handler event="mousedown" button="0" phase="capturing">
  1058.         _startScroll();
  1059.       </handler>
  1060.       <handler event="mouseover" button="0" phase="capturing">
  1061.         _continueScroll();
  1062.       </handler>
  1063.       <handler event="mouseup" button="0" phase="capturing">
  1064.         _stopScroll();
  1065.       </handler>
  1066.       <handler event="mouseout" button="0" phase="capturing">
  1067.         _pauseScroll();
  1068.       </handler>
  1069.       <handler event="contextmenu">
  1070.         _createTabsList(event, this._side);
  1071.       </handler>
  1072.       <handler event="dblclick" button="0" phase="capturing">
  1073.         event.stopPropagation();
  1074.       </handler>
  1075.     </handlers>
  1076.  
  1077.   </binding>
  1078.  
  1079.   <!--
  1080.       we don't use this for Firefox 3.0 +
  1081.       we leave it here because some theme looking for this
  1082.    -->
  1083.   <binding id="tabbrowser"
  1084.       extends="chrome://browser/content/tabbrowser.xml#tabbrowser">
  1085.  
  1086.     <implementation>
  1087.  
  1088.     </implementation>
  1089.  
  1090.   </binding>
  1091.  
  1092. </bindings>
  1093.